package com.tools.traceTool
{
	import flash.display.Stage;
	import flash.events.AsyncErrorEvent;
	import flash.events.ErrorEvent;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.StatusEvent;
	import flash.events.TimerEvent;
	import flash.system.System;
	import flash.text.StyleSheet;
	import flash.text.TextField;
	import flash.utils.Timer;
	
// DEF #####################################################
public class ReceiverCore extends TraceConfig
{
// DEF #####################################################
private		var		stage:Stage=new Stage();
private		const	FILL_UP_CHAR:String=' ';
private		var		css:String;
//protected	var		w:Number=0;
//protected	var		h:Number=0;
private		var		ClassLength:uint;
private		var		style:String='txt';
private		var		fontSize:uint=14;
private		var		_Counter:uint=0;
private		var		isRawText:Boolean=false;
protected	var		clearEnable:Boolean=true;
protected	var		write2Top:Boolean=true;
protected	var		inverseStyle:Boolean=true;

private		var		tf:TextField=new TextField();
private		var		sign:TextField=new TextField();
private		var		clipBoardSign:TextField=new TextField();
private		var		signChecker:Timer=new Timer(TraceConfig.SIGN<<3);
private		var		clipBoardSignRemover:Timer=new Timer(TraceConfig.SIGN<<2,1);
//	constructor 
public function ReceiverCore()
{
	setEvents();
//	setStyleSheet();
/*
	tf.autoSize=TextFieldAutoSize.LEFT;
	tf.name='TraceLayer';
	tf.multiline=true;
	tf.selectable=true;
	tf.mouseEnabled=true;
//	tf.mouseEnabled=false;
	tf.condenseWhite=false;
	tf.background=true;
	tf.htmlText=
		'<br/><p class="l">  * to <b>cut</b> out the traced text then press 				<b>Ctrl</b>  <b>X</b>   </p>'+
		'<br/><p class="l">  * to <b>copy</b> the traced text to the clipboard press		<b>Ctrl</b>  <b>C</b>   </p>'+
		'<br/><p class="l">  * to change the <b>automatic reload clear</b> then press		<b>Ctrl</b>  <b>A</b>   </p>'+
		'<br/><p class="l">  * to change the color <b>style</b> then press  				<b>Ctrl</b>  <b>S</b>   </p>'+
		'<br/><p class="l">  * to change the writing <b>direction</b> then press			<b>Ctrl</b>  <b>D</b>   </p>'+
		'<br/><p class="l">  * to change the <b>font size</b> then press					<b>Ctrl</b> <b>+/-</b>   </p>'+
		'<br/>';
	addChild(tf);

	var format:TextFormat=new TextFormat();
	format.bold=true;
	format.align=TextFieldAutoSize.RIGHT;
	format.size=16;
	format.font='_typewriter';
	sign.name="sign";
	sign.multiline=true;
	sign.background=true;
	sign.mouseEnabled=false;
	sign.condenseWhite=false;
//	sign.borderColor=0xFFFFFF;
	sign.backgroundColor=0xFF0000;
	sign.defaultTextFormat=format;
	sign.autoSize=TextFieldAutoSize.RIGHT;
	localMsg('(-)');
	addChild(sign);

	clipBoardSign.name='clipBoardSign';
	clipBoardSign.textColor=0;
	clipBoardSign.multiline=false;
	clipBoardSign.background=true;
	clipBoardSign.backgroundColor=0x00FF00;
	clipBoardSign.defaultTextFormat=format;
	clipBoardSign.autoSize=TextFieldAutoSize.RIGHT;
	clipBoardSign.text='';
	clipBoardSignRemover.addEventListener(TimerEvent.TIMER,hideClipBoard);
	onResize();
 */
	
	(new ReceiverBase()).client=this;
	signChecker.addEventListener(TimerEvent.TIMER,onLostContact);
}
//	it is automaticaly called... if you call it clears the window
public	function connected():void	{clear();signChecker.start();}

//public function callback(id:String,...args:*=undefined):void{this[id](...args);}
public function callback(id:String,content:*=undefined):void{this[id](content);}

public function Sign():void
{
	signChecker.reset();
	signChecker.start();
	sign.background=false;
	switch(sign.text)
	{
		case'(|)':	sign.text='(/)';	onResize();return;
		case'(/)':	sign.text='(-)';	onResize();return;
		case'(-)':	sign.text='(\\)';	onResize();return;
		default:	sign.text='(|)';	onResize();return;
	}
}
public function addText(className:String,args:Array):void
{
	tf.htmlText=
		(write2Top?'':tf.htmlText)+
		'<p class="'+(String(style).length?style:'txt')+'">'+
			Counter(true)+specialchars(prepare(className)+'|'+String(args))+
		'</p>'+
		(write2Top?tf.htmlText:'');
	sign.background?Sign():null;
	signChecker.reset();
	signChecker.start();
}
// Private ##################################################
//
private function clear():void						{if(clearEnable){_Counter=0;tf.text='';}}
private function Counter(inc:Boolean=false):String	{return	inc?_Counter>999?''+(_Counter++)+'\t':''+(_Counter++)+'\t\t':_Counter>999?''+_Counter+'\t':''+_Counter+'\t\t';}
private function prepare(name:String):String
{
	if(!name.length){return fillUp(ClassLength);}
	name.length>ClassLength?ClassLength=name.length:null;
	name+=fillUp(ClassLength-name.length);
	return name;
}
private function fillUp(u:uint):String	{return	u>0?FILL_UP_CHAR+fillUp(--u):'';}
private function localMsg(...args):void
{
	String(sign.htmlText).length>3000?sign.text='':null;
	sign.htmlText='<p class="l">'+specialchars(String(args))+'</p>'+sign.htmlText;
	sign.background=true;
	onResize();
}
private function specialchars(s:String):String
{
	return	(s
		.replace(isRawText?' ':RegExp(/\n/g),	' ')
		.replace(RegExp(/\r/g),					'')
		.replace(RegExp(/</g),					'&lt;')
		.replace(RegExp(/\[class ([\w]+)\]/),	'$1')
		.replace(RegExp(/\[class ([\w]+)\]/g),	'[C $1]')
		.replace(RegExp(/\[object ([\w]+)\]/g),	'[$1]')
	);
}
private function setStyleSheet():void
{
	resetCss();
	var styleSheet:StyleSheet=new StyleSheet();
		styleSheet.parseCSS(convertCSS(css));
	tf. styleSheet=styleSheet;
}
private	function convertCSS(StyleSheetText:String):String
{
	return StyleSheetText.
		replace(RegExp(/font-family/gi),		'fontFamily').
		replace(RegExp(/font-size/gi),			'fontSize').
		replace(RegExp(/font-style/gi),			'fontStyle').
		replace(RegExp(/font-weight/gi),		'fontWeight').
		replace(RegExp(/letter-spacing/gi), 	'letterSpacing').
		replace(RegExp(/margin-left/gi),		'marginLeft').
		replace(RegExp(/margin-right/gi),		'marginRight').
		replace(RegExp(/text-align/gi), 		'textAlign').
		replace(RegExp(/text-decoration/gi),	'textDecoration').
		replace(RegExp(/text-indent/gi),		'textIndent');
}
// Events ##################################################
//
private	function setEvents():void
{
	stage.addEventListener(ErrorEvent.ERROR,					onError);
	stage.addEventListener(StatusEvent.STATUS,					onStatus);
	stage.addEventListener(IOErrorEvent.IO_ERROR,				onIOError);
	stage.addEventListener(AsyncErrorEvent.ASYNC_ERROR,			onAsyncError);
	stage.addEventListener(SecurityErrorEvent.SECURITY_ERROR,	onSecurityError);
	
	stage.addEventListener(Event.RESIZE,			onResize);
	stage.addEventListener(Event.SCROLL,			onScroll);

//	stage.addEventListener(KeyboardEvent.KEY_DOWN,	onKeybDown);
	stage.addEventListener(KeyboardEvent.KEY_UP,	onKeybUp);

	stage.addEventListener(MouseEvent.CLICK,		onClick);
}
private	function allEvents(e:Event,txt:String=''):void{trace(txt);Sign();}
private	function onLostContact(e:TimerEvent):void
{
	trace('onLostContact');
	sign.background=true;
	signChecker.reset();
	(new ReceiverBase()).connect();
}
protected function onResize(e:Event=null):void		
{
//	w=stage is Stage?stage.stageWidth:width;
//	h=stage is Stage?stage.stageHeight:height;
//	sign.x=w-sign.width-15;sign.y=h-sign.height-15;
//	clipBoardSign.x=w-clipBoardSign.width-15;clipBoardSign.y=0;
}
private	function onScroll(e:Event):void				{allEvents(e);}
//private	function onKeybDown(e:KeyboardEvent):void{}
//
private	function onKeybUp(e:KeyboardEvent):void
{
	allEvents(e,e.keyCode+"	key:"+e.keyLocation+','+e.charCode+"	ctrl:"+e.ctrlKey+"	shift:"+e.shiftKey+"	alt:"+e.altKey);
	if(!e.ctrlKey){return;}
	switch(e.charCode)
	{
		case	99:
					if(tf.selectionBeginIndex!=tf.selectionEndIndex){return;}
					clipBoardSign.text='the displayed data was copyed to the clip board';
					System.setClipboard(tf.text);
					break;
		case	120:
					String(tf.text).length?System.setClipboard(tf.text):null;
					clipBoardSign.text='the displayed data was moved to the clip board';
					var cE:Boolean=clearEnable;
					clearEnable=true;
					clear();
					clearEnable=cE;
					break;
		case	97:
					clearEnable=!clearEnable;
					clipBoardSign.text='the automatic clear is '+(clearEnable?"enabled":"disabled")+' now';
					break;
		case	45:
					fontSize>3?fontSize--:null;
					fontSize--;
		case	43:
					fontSize++;
					setStyleSheet();
					clipBoardSign.text='the font size was changed to '+fontSize+' px';
					break;
		case	115:
					inverseStyle=!inverseStyle;
					clipBoardSign.text='the style was changed now';
					setStyleSheet();
					break;
		case	100:
					write2Top=!write2Top;
					clipBoardSign.text='the text direction was changed, now is '+(write2Top?'up side down':'normal');
					setStyleSheet();
					break;
					
		default:	return;
	}
	clipBoardSignRemover.reset();
	clipBoardSignRemover.start();
//	addChild(clipBoardSign);
}
private	function	hideClipBoard(e:TimerEvent):void	{/*removeChild(clipBoardSign);*/}
private	function	onClick(e:MouseEvent):void
{
	allEvents(e,'local [x;y]:['+e.localX+';'+e.localY+']	Stage[x;y]:['+e.stageX+';'+e.stageY+']	d:'+e.delta);

	sign.background?(new ReceiverBase()).connect():null;

}
private	function onError(e:ErrorEvent):void{allEvents(e,e.text);}
//		#############################################
private	function onIOError(e:IOErrorEvent):void				{allEvents(e,e.text);}
private	function onAsyncError(e:AsyncErrorEvent=null):void	{style='l';localMsg('	AsyncError	'+e.target+'	'+e.text);}
private	function onSecurityError(e:SecurityErrorEvent):void	{style='l';localMsg('	SecurityError'+e.target+'	'+e.text);}
private	function onStatus(e:StatusEvent):void				{style='l';localMsg('	Status		'+e.target+'	'+e.level);}
private	function resetCss():void
{
	tf.backgroundColor=inverseStyle?0:0xFFFFFF;
	sign.textColor=inverseStyle?0xFFFFFF:0;
	css=
	'p	{'+
		'font-family:	_typewriter;'+
		'font-size:		'+fontSize+';'+
		'letter-spacing:0;'+
		'text-align:	left;'+
		'text-decoration:none;'+
		'text-indent:	0;'+
	'}'+
	'.n	{'+	//	NOTICE		text
		(inverseStyle?'color:	#FFFFFF;':'color:	#000000;')+
	'}'+
	'.h	{'+		//	HIGHLIGHTED	message
		(inverseStyle?'color:	#FFFFFF;':'color:	#000000;')+
		'font-weight:	bold;'+
		'textDecoration:underline;'+
	'}'+
	'.w	{'+		//	WARNING	orange	message
		(inverseStyle?'color:	#FF9900;':'color:	#FF6600;')+
		'font-weight:	bold;'+
	'}'+
	'.e	{'+		//	ERROR	red		message
		(inverseStyle?'color:	#FF3333;':'color:	#CC0000;')+
		'font-weight:	bold;'+
	'}'+
	'.g	{'+		//	green		message
		(inverseStyle?'color:	#00FF00;':'color:	#00CC00;')+
		'font-weight:	bold;'+
	'}'+
	'.b	{'+		//	blue		message
		(inverseStyle?'color:	#9999FF;':'color:	#0000CC;')+
		'font-weight:	bold;'+
	'}'+
	'.y	{'+		//	yellow		message
		(inverseStyle?'color:	#FFFF00;':'color:	#999900;')+
		'font-weight:	bold;'+
	'}'+
	'.m	{'+		//	magenta		message
		(inverseStyle?'color:	#FF00FF;':'color:	#CC00CC;')+
		'font-weight:	bold;'+
	'}'+
	'.c	{'+		//	cyan		message
		(inverseStyle?'color:	#00FFFF;':'color:	#009999;')+
		'font-weight:	bold;'+
	'}'+
	'.s	{'+		//	silver		message
		(inverseStyle?'color:	#999999;':'color:	#666666;')+
		'font-weight:	bold;'+
	'}'+
	'.l	{'+		//	LOCAL		message
		(inverseStyle?'color:	#FFFFFF;':'color:	#000000;')+
		'font-weight:	normal;'+
		'font-style:	italic;'+
	'}'+
	'';
}
// END #####################################################
}	//class
}	//package
// END #####################################################